#include <iostream>
#include <cstdio>
#include<cstring>
#include<cstdlib>
#include<cstdbool>
#include<unistd.h>
#include<sys/types.h>
#include<wait.h>

#define COMMAND_SIZE 1024 
#define FORMAT "[%s@%s %s]# "

#define MAXARGC 128
char*  g_argv[MAXARGC];
int g_argc = 0;

char cwd[1024];
char cwdenv[1024];
const char*  GetUser()
{
  const char* username = getenv("USER");
  return username == NULL?"None":username;
}

const char* GetHostname()
{
  const char* hostname  = getenv("HOSTNAME");
  return hostname == NULL?"None":hostname;
}

const char* GetPwd()
{
 // const char* pwd = getenv("PWD");
  const char* pwd = getcwd(cwd,sizeof(cwd));
  if(pwd != NULL)
  {
    snprintf(cwdenv,sizeof(cwdenv),"PWD=%s",cwd);
    putenv(cwdenv);
  }
  return pwd == NULL?"None":pwd;
}

const char* Gethome()
{
  const char* home = getenv("HOME");
  return home == NULL?"None":home;
}

#define SLASH "/"
std::string Dirname(const char* pwd)
{
  std::string dir = pwd;
  if(dir == SLASH) return SLASH;
  auto pos = dir.rfind(SLASH);
  if(pos == std::string::npos) return "bug";
  return dir.substr(pos+1);
}

void makecommandline(char cline[], int size)
{
  snprintf(cline,size,FORMAT,GetUser(),GetHostname(),Dirname(GetPwd()).c_str());
}

void printfcommandline()
{
  char cline[COMMAND_SIZE];
  makecommandline(cline,sizeof(cline));
  printf("%s",cline);
  fflush(stdout);
}

bool Getcommandline(char* commandline, int size)
{
  char* r = fgets(commandline,size,stdin);
  if(r == NULL) return false;
  commandline[strlen(commandline)-1] = 0;
  if(strlen(commandline) == 0) return false;
  return true;

}

bool commandanslyse(char* commandline)
{
    g_argc = 0;
    g_argv[g_argc++] = strtok(commandline," ");
    while((bool)(g_argv[g_argc++] = strtok(nullptr," ")));
    g_argc--;
    return g_argc>0?true:false;
}

void printfargv()
{
  int i = 0;
  printf("%d\n",g_argc);
  for(i = 0; g_argv[i]; i++)
  {
    printf("g_argv[%d]->%s\n",i,g_argv[i]);
  }
}

bool Checkandbuild()
{
  std::string cmd = g_argv[0];
  if(cmd == "cd")
  {
    if(g_argc == 1)
    {
      std::string home = Gethome();
      if(home.empty()) return true;
      chdir(home.c_str());
    }
    else
    {
      std::string where = g_argv[1];
      chdir(where.c_str());
    }
    return true;
  }
  return false;
}

int Execute()
{
   pid_t id = fork();
   if(id == 0)
  {
   //子进程
   execvp(g_argv[0],g_argv); 
   exit(1); 
   }
   else
   {
      //父进程
      pid_t rid = waitpid(id,nullptr,0);
      (void)rid;
    }
  return 0;
}

int main()
{

  while(1)
  {

    //printf("[%s@%s %s]#",GetUser(),GetHostname(),GetPwd());
    printfcommandline();
    //获取数据
    char Commandline[COMMAND_SIZE];
    if(Getcommandline(Commandline,sizeof(Commandline)))
    {
      // printf("%s\n",Commandline);

    }
    else
    {
      continue;
    }
    //此时一定已经获取数据
    if(commandanslyse(Commandline)== false) continue;
   // printfargv();
   
    //判断是否是内键命令
    if(Checkandbuild()) continue;

   // 执行命令
    Execute();
  }
    return 0;
}
